package org.shoukaiseki.inittable.handle.database;

import org.shoukaiseki.common.logger.LoggerConstants;
import org.shoukaiseki.common.utils.StringUtils;
import org.shoukaiseki.inittable.config.TableBuildProperties;
import org.shoukaiseki.inittable.domain.SksInitTableVersion;
import org.shoukaiseki.inittable.domain.SksInitTableVersionQO;
import org.shoukaiseki.inittable.domain.TableInfo;
import org.shoukaiseki.inittable.logger.InitTableLoggers;
import org.shoukaiseki.inittable.mapper.SksInitTableVersionMapper;
import org.slf4j.Logger;
import org.springframework.beans.factory.config.BeanDefinitionHolder;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;


public abstract class BaseInitTableHandle {

    public static final Logger logger = InitTableLoggers.DEFAULT_LOGGER;

    private TableBuildProperties tableBuildProperties;

    protected String sksInitTableVersion ="sks_init_table_version";

    protected SksInitTableVersionMapper sksInitTableVersionMapper;

    protected  Connection conn;
    protected TableInfo tableInfo;
    protected BeanDefinitionHolder bean;
    protected Class<?> clazz;

    protected String tableName;

    protected ResultSet resultSet;

    protected Statement statement;

    protected String lastExecuteSql;

    private List<String> errorIndexSqlList;

    private List<String> errorTriggerSqlList;

    /**
     * 执行的语句
     */
    private List<String> executeSqlList;

    public BaseInitTableHandle(Connection conn,TableInfo tableInfo){
        this.conn=conn;
        if(tableInfo!=null){
            this.tableInfo=tableInfo;
            this.tableName=tableInfo.getName();
        }
    }



    public abstract void buildColumn();

    /**
     * 执行中未存在错误返回false
     * @param initType (initType&0b10)>0=true 重建索引,存在则先删除
     * @return
     */
    public  void buildIndex(int initType){
    }

    /**
     * 执行中未存在错误返回false
     * @param initType (initType&0b1000)>0=true 重建限制,存在则先删除
     * @return
     */
    public void buildConstraint(int initTYpe){

    }

    /**
     * 执行中未存在错误返回false
     * @param initType (initType&0b0100)>0=true 重建触发器,存在则先删除
     * @return
     */
    public  void buildTrigger(int initType){
    }

    /**
     * 初始化table版本管理表
     *
     * @param reset   true:清除table版本管理表,推荐进行drop
     */

    public abstract void buildSksInitTableVersion(boolean reset);

    /**
     * 获取表版本号
     * @return
     */
    public abstract SksInitTableVersion selectTableVersion(String tableName) throws SQLException;

    /**
     * 获取表版本号列表
     * @param searchValueList
     * @return
     */
    public abstract List<SksInitTableVersion> selectTableVersionList(SksInitTableVersionQO sksInitTableVersion);

    public abstract void updateCurrentMd5();

    public abstract void updateLastMd5();

    /**
     * 设置当前版本号
     */
    public abstract void insertTableVersion(SksInitTableVersion sksInitTableVersion);

    /**
     * 更新版本好等信息
     * @param sksInitTableVersion
     */
    public abstract void updateTableVersion(SksInitTableVersion sksInitTableVersion);

    /**
     *
     * @param tableInfo
     */
    public abstract void insertTableInfoToVersion(TableInfo tableInfo);



    public List<String> getErrorIndexSqlList() {
        return errorIndexSqlList;
    }


    public List<String> getErrorTriggerSqlList() {
        return errorTriggerSqlList;
    }


    public List<String> getExecuteSqlList() {
        return executeSqlList;
    }

    public void addExecuteSql(String sql) {
        if(StringUtils.isEmpty(sql)){
            return;
        }
        if (executeSqlList ==null) {
            executeSqlList = new ArrayList();
        }
        executeSqlList.add(sql);
    }

    public void addErrorTriggerSql(String sql) {
        if(StringUtils.isEmpty(sql)){
            return;
        }
        if (errorTriggerSqlList ==null) {
            errorTriggerSqlList = new ArrayList();
        }
        errorTriggerSqlList.add(sql);
    }

    public void addErrorIndexSql(String sql){
        if(StringUtils.isEmpty(sql)){
            return;
        }

        if (errorIndexSqlList ==null) {
            errorIndexSqlList = new ArrayList<>();
        }
        errorIndexSqlList.add(sql);
    }


    public int createStatementExecuteUpdate(String sql) throws SQLException {
        this.lastExecuteSql=sql;
        logger.debug("{}{}", LoggerConstants.PREFIX,sql);
        statement = conn.createStatement();
        int i = statement.executeUpdate(sql);
        return i;
    }


    public ResultSet selectBySql(String sql) throws SQLException {
        this.lastExecuteSql=sql;
        logger.debug("{}{}", LoggerConstants.PREFIX,sql);
        statement = conn.createStatement();
        resultSet = statement.executeQuery(sql);
        return resultSet;
    }

    public void closeStatement(){
        closeResultSet();
        try {
            if(statement!=null){
                statement.close();
            }
        } catch (Throwable t) {
            logger.debug("t",t);
        }
        statement=null;
        resultSet=null;
    }

    public void closeResultSet(){
        try {
            if(resultSet!=null){
                resultSet.close();
            }
        } catch (Throwable t) {
            logger.debug("t",t);
        }
        resultSet=null;
    }

    public void setBeanDefinitionHolder(BeanDefinitionHolder bean){
        this.bean=bean;
    }

    public void setClazz(Class<?> clazz) {
        this.clazz=clazz;
    }

    public String getLastExecuteSql() {
        return lastExecuteSql;
    }

    public TableBuildProperties getTableBuildProperties() {
        return tableBuildProperties;
    }

    public void setTableBuildProperties(TableBuildProperties tableBuildProperties) {
        this.tableBuildProperties = tableBuildProperties;
    }

    public void setSksInitTableVersionMapper(SksInitTableVersionMapper sksInitTableVersionMapper){
        this.sksInitTableVersionMapper=sksInitTableVersionMapper;
    }
}
